To Do
- JDBC与JPA的区别
JDBC是数据库访问的标准;JPA是ORM的标准
JPA和JDBC之间的主要区别是抽象层次:JDBC是与数据库交互的低级标准,JPA是同一目的的较高标准
JDBC是JPA的前身
- Hibernate与Mybatis与Spring Data
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装
【开发难度大】MyBatis 本是apache的一个开源项目iBatis,着力于POJO与SQL之间的映射关系
Spring Data是一个用于简化数据库访问,并支持云服务的开源框架。其主要目标是使得对数据的访问变得方便快捷,并支持map-reduce框架和云计算数据服务
【SQL的自由度低】- Predicate接口中的CriteriaQuery与CriteriaBuilder
CriteriaQuery:表达式查询语句
CriteriaBuilder:面向对象查询语句(.equal(),.and(),.or(),.like())
- JDBC事务和JTA事务
JDBC的一切行为包括事务是基于一个Connection的(在JDBC中是通过Connection对象进行事务管理(常用的和事务相关的方法是: setAutoCommit、commit、rollback等)
Java Transaction API是一个Java企业版 的应用程序接口,在Java环境中,允许完成跨越多个XA资源的分布式事务
【处理分布式事务】- 关于关联对象的懒加载处理
Question:
- test中的数据库操作,会报tansactionrequired异常,事务会自动回滚roll back
在test方法上手动设置@Transactional可以声明事务
在test方法上手动设置@Rollback(false),可以禁止回滚
- 进行save(Object)操作时,如果对象中有主键信息,会自动切换为修改操作
(因此:增、改均可以使用同一个方法save)
【小tips:可以在页面设置隐藏td用于存放id,可以根据实际情况进行自动判断,进行增加或者修改】
一. 概述
为了简化并统一持久层的各种实现技术的API,Spring Data提供了一套标准的API,整合不同持久层
spring-data-commons:一套标准API
spring-data-jpa 基于整合JPA实现
1. 简介
SpringData支持的持久层技术:
- NoSQL 存储:
MongoDB (文档数据库)
、Neo4j(图形数据库)
、Redis(键/值存储)
、Hbase(列族数据库)
- 关系数据存储技术:
JDBC
、JPA
JDBC:(Java Data Base Connectivity),用于直接调用SQL命令,面向数据库
JPA:(Java Persistence API),操作实体对象,免除编写繁琐的SQL,面向对象
【HIbernate即JPA的一种实现
】
2. 操作步骤
- 配置 Spring 整合 JPA
- 在 Spring 配置文件中配置 Spring Data,让 Spring 为声明的接口创建代理对象。
- 声明持久层的接口,该接口继承自Repository接口(
开发中一般继承其子接口
),并注入实体类及其主键类型
【spring容器实际通过AOP为我们提供的是SimpleJpaRepository(JpaRepository的实现类)的对象
】- 在接口中声明需要的Method
- 使用Spring为这些接口创建代理实例(
也可以通过JavaConfig,或者XML配置
)<jpa:repositories base-package="com.acme.repositories"/> (XML配置语句)
- 获取Repository实例注入并使用它
1 | // 1.声明一个继承自Repository的接口 |
3. Repository接口
Spring-data-commons中提供
Repository接口是 Spring Data 的一个核心接口,但是并不提供任何method,为一个名义接口
开发者在自定义子接口中定义method
Spring Data让我们可以只定义接口,只要遵循 Spring Data的规范,就
无需写实现类
4. Repository子接口
标准接口位于Spring-data-commons
扩展接口位于Spring-data-jpa
- CrudRepository 标准接口 (
提供了最基本的对实体类的CRUD操作
)
增删改:save、delete、deleteAll
查:findAll、findOne、count
- PagingAndSortingRepository 标准接口(
继承自CrudRepository,提供了分页与排序功能
)
排序
:Iterable<T> findAll(Sort sort);
分页查询(含排序功能)
:Page<T> findAll(Pageable pageable);
- JpaRepository 扩展接口(
该接口提供了JPA的相关功能
)
|method|Description|
|:-|:-|:-|
|List<T> findAll()
|查找所有实体|
|List<T> findAll(Sort sort)
|排序、查找所有实体|
|List<T> save(Iterable<? extends T> entities)
|保存集合|
- JpaSpecificationExecutor 扩展接口(
不属于Repository体系,实现一组JPA Criteria查询相关的方法
)- Specification:Spring Data JPA提供的查询规范,用于复杂的查询(
类似于QBC查询
)- 自定义Repository子接口
二.操作流程
在Spring Data repository 抽象的接口中心是仓库(Repository).
1. 定义repository接口
自定义一个接口,继承某个Repository的子接口(
需要泛型注入Entity类和一个主键类型
)
- 子接口举隅
如果对象要实现CRUD操作,需要继承CrudRepository接口
如果还要在此基础上实现分页查询,需要继承PagingAndSortingRepository接口
- repository调整
除了继承Spring Data接口,也能通过@RepositoryDefinition声明自定义的Repository接口
在自定义接口中,可以选择性地暴露某些method,从而实现定义自己的抽象
【暴露的接口,会通过动态代理获取实现类(如SimpleJapRepository)的method】
1 | // 定义一个基础接口,供所有的domain接口使用(暴露findOne,save方法) |
2. 定义查询method
Repository代理提供两种方式获取特定查询
依据方法名直接导出查询
+手动定义查询
2.1 查找策略
可用于仓库基础结构来解决查询
- 实现方式:
xml配置(query-lookup-strategy属性)
注解声明(Enable${store}Repositories中声明queryLookupStrategy属性)
- 策略分类
CREATE:通过查询方法名构建一个特别的数据查询
USE_DECLARED_QUERY:尝试找到一个声明查询并在找不到的时候抛出一个异常
CREATE_IF_NOT_FOUND:综合上述两者的功能
2.2 创建查询
内置的查询生成器会剔除方法名中的关键字(
诸如find/read/query/count/get...by
),并解析剩下的内容
Distinct标志:
by:后面一般为查询条件,多个条件以and/or连接
属性表达式你也可以使用可支持的操作比如Between(区间查询),LessThan,GreaterThan,Like(模糊查询)
方法解析支持为某些属性设置一个IgnoreCase标志
通过增加一个OrderBy字段实现按照属性排序
1 | public interface PersonRepository extends Repository<user,Long>{ |
2.3 属性表达式
用于自定义条件查询
属性表达式只能引用实体类的直接属性
内置查询器,依据固定规律,解析method名中的attribute作为查询条件
1 | // 解析:1. 创建属性遍历x.address.zipCode |
2.4 特殊参数处理
- Pageable:
- Slice:
- Sort:
1 | // 利用Spring框架提供的Pageable实例,来动态地实现添加分页 |
2.5 限制查询
关键字:
first
、top
(用于限制结果数)
默认值为1,可以交替使用
可以使用distinct
1 | User findFirstByOrderByLastnameAsc(); |
2.6 流查询
Stream
查询方法能对以JAVA 8的Stream为返回的结果进行逐步处理
一个数据流可能包裹底层数据存储特定资源,因此在使用后必须关闭。 你也可以使用close()方法或者JAVA 7 try-with-resources区块手动关闭数据流
1 | "select u from User u") ( |
3. 创建repository实例
使用namespace,创建repository接口的bean实例
- XML配置
每一个Spring Data模块都包含repositories元素,因此简单的基于base-package定义即可进行Spring扫描
1 |
|
- JavaConfig
在一个JavaConfig类中使用
@Enable${store}Repositories
声明来触发repository的构建
1 | // JPA声明 |
- 独立使用
可以在spring容器外使用repository组件
1 | RepositoryFactorySupport factory = … // Instantiate factory here |
4. 自定义实现repositories
允许实现自定义的功能(
包括CRUD和查询功能
)
4.1 针对单一repositories
自定义接口,并实现接口的方法,使用自定义的
1 | interface UserRepositoryCustom { |
4.2 针对所有repositories
添加自定义行为到所有的repository中
1 |
|
三. 常用API(★★★)
本章节主要概述自定义数据库操作语句(
即Spring框架中repository实现类中未定义的sql
)
1. 条件查询
1.1 根据method名自动生成
即利用属性表达式(Property expressions)
在接口中定义方法(
利用关键字
+按照固定格式
),无需实现,内置查询器会自动生成并在调用方法时注入相应的查询语句
精确查询一列:findBy列名
模糊查询一列:findBy列名Like
精确查询多列:findBy列名And列名Like
【按照驼峰命名】
1.2 配置@Query (★)
当方法名不按命名规则写的查询方法,可以配置@Query 绑定JPAL语句或者SQL语句
使用
JPAL
语句,设置属性nativeQuery=false
【实际上,JPAL语句,在语法上完全同HQL,只是称谓不同
】使用
SQL
语句,设置属性nativeQuery=true
1.3 实体类上配置@NamedQuery
在接口的方法上配置
@Query
,并在实体类上定义@NamedQuery(name="方法名",query="语句")
1 | public interface StandardRepository extends JpaRepository<Standard, Integer> { |
2. 带条件修改
使用
@Query
注解完成 , 搭配使用@Modifying
标记修改、删除操作
在测试test中进行增删改操作时,需要在test方法上设置事务,并手动定义不rollback
1 | // 定义修改的方法 |
3. 分页查询
- Spring Data提供的标准接口PagingAndSortingRepository中,定义了实现分页的方法
Page<T> findAll(Pageable pageable)
- 参数:
SpringData提供了PageRequest对象,作为Pageable接口的实现类
【注意:PageRequest的page页码从0开始
】
public PageRequest(int page, int size)
【构造器】public PageRequest(int page, int size, Sort sort)
- 返回值:
分页的查询结果,会被自动封装为Page<T>
总页数:TotalPages
页面详情:TotalElements
1 | // 实例化Pageable对象(传入参数:当前页码,当前页总记录数) |
4. 查询关键字
在method名称中可以使用的
四. 参考文档
1. 简介
1.1 命名空间(namespace)
Spring Data的JPA模块包含一个允许定义存储库bean的自定义命名空间(
包含JPA特有的某些特征和元素属性
)
1 |
|
1.2 注解配置
Spring Data JPA存储库支持不仅可以通过XML命名空间激活,还可以通过JavaConfig使用注释
1 |
|